/*
    Heart of Gold engine management system
    Copyright (C) 2004 Heart of Gold development team

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package com.heartOfGold.view;

/*
 * The Runtime Variables page for the Megasquirt HOG_Component
 * @author Ryan Higgins
 * @date May 2004
 */
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JProgressBar;
import javax.swing.Box;

import com.heartOfGold.controller.Fuel;
import com.heartOfGold.model.megasquirtECU.MegasquirtINC;

import java.io.*;

public class FuelRunTime extends JPanel implements ActionListener {
    private FuelMaster master;
    private Fuel model;
    private RealRequester requester;
    private JPanel buttons;
    private JButton done;
    private LabelFieldBar seconds, map, coolant, baro, mat, tps, rpm, batt, pw;
    private LabelField gamma, ego, barom, warm, airDens, ve, acc;

    private class RealRequester extends Thread {
        private FuelRunTime panel;
        private Fuel model;
        private long waitTime;

        public RealRequester(final FuelRunTime p, final Fuel mod) {
            panel = p;
            model = mod;
            waitTime = 1000 / 50;
        }

        public void setWait(final long wait) {
            waitTime = wait;
        }

        public long getWait() {
            return waitTime;
        }

        public void run() {
            //TODO fix empty catch statements
            while (true) {
                if (panel.isShowing()) {
                    try {
                        model.getRealTime();
                    } catch (IOException e) {
                    }
                    try {
                        sleep(waitTime);
                    } catch (InterruptedException e) {
                    }
                    yield();
                }
            }
        }
    }

    private class LabelFieldBar extends JPanel {
        private JLabel theLabel;
        private JTextField theField;
        private JProgressBar theBar;
        private int fieldColumns;
        private Dimension labelSize;

        public LabelFieldBar(final String label, final int min, final int max) {
            JLabel my = new JLabel("Injector Pulse Length (ms)");
            labelSize = new Dimension(my.getPreferredSize());
            fieldColumns = 5;
            theLabel = new JLabel(label);
            theLabel.setPreferredSize(labelSize);
            theField = new JTextField(fieldColumns);
            theField.setEditable(false);
            theField.setText("0");
            theField.setHorizontalAlignment(JTextField.CENTER);
            theBar = new JProgressBar(min, max);
            add(theLabel);
            add(theField);
            add(theBar);
        }

        public void update(final double fieldValue, final int barValue) {
            theField.setText("" + fieldValue);
            theBar.setValue(barValue);
        }

    }

    private class LabelField extends JPanel {
        private JLabel theLabel;
        private JTextField theField;
        private int fieldColumns;
        private Dimension labelSize;

        public LabelField(final String label) {
            JLabel my = new JLabel("Injector Pulse Length (ms)");
            labelSize = new Dimension(my.getPreferredSize());
            fieldColumns = 5;
            theLabel = new JLabel(label);
            theLabel.setPreferredSize(labelSize);
            theField = new JTextField(fieldColumns);
            theField.setEditable(false);
            theField.setText("0");
            theField.setHorizontalAlignment(JTextField.CENTER);
            add(theLabel);
            add(theField);
        }

        public void update(final double fieldValue) {
            theField.setText("" + fieldValue);
        }

    }

    public FuelRunTime(final FuelMaster m,
            final Fuel mod) {
        master = m;
        model = mod;
        requester = new RealRequester(this, mod);
        requester.start();
        setBorder(BorderFactory.createTitledBorder("Digital Dashboard"));
        // setup fields and stuff

        // setup the real time variables
        JPanel realTime = new JPanel(new GridLayout(10, 1));
        seconds = new LabelFieldBar("Seconds", 0, 255);
        realTime.add(seconds);
        map = new LabelFieldBar("MAP (KPa)", 0, 255);
        realTime.add(map);
        coolant = new LabelFieldBar("Coolant (F)", 0, 255);
        realTime.add(coolant);
        baro = new LabelFieldBar("Barometer (KPa)", 0, 255);
        realTime.add(baro);
        mat = new LabelFieldBar("Manifold Air Temp", 0, 255);
        realTime.add(mat);
        tps = new LabelFieldBar("Throttle Position (%)", 0, 255);
        realTime.add(tps);
        rpm = new LabelFieldBar("RPM", 0, 50);
        realTime.add(rpm);
        batt = new LabelFieldBar("Battery (V)", 0, 18);
        realTime.add(batt);
        pw = new LabelFieldBar("Injector Pulse Length (ms)", 0, 26);
        realTime.add(pw);
        gamma = new LabelField("Gamma");
        realTime.add(gamma);
        realTime.setBorder(BorderFactory
                .createTitledBorder("Real-Time Variables"));
        add(realTime);

        // setup the enrichments
        JPanel corrections = new JPanel(new GridLayout(3, 2));
        ego = new LabelField("EGO");
        corrections.add(ego);
        barom = new LabelField("Barometer");
        corrections.add(barom);
        warm = new LabelField("Warmup");
        corrections.add(warm);
        airDens = new LabelField("Air Density");
        corrections.add(airDens);
        ve = new LabelField("Volumetric Efficiency");
        corrections.add(ve);
        acc = new LabelField("Acceleration (ms)");
        corrections.add(acc);
        corrections.setBorder(BorderFactory
                .createTitledBorder("Corrections/Enrichments (%)"));

        // setup buttons
        buttons = new JPanel();
        done = new JButton("Done");
        done.addActionListener(this);
        buttons.add(done);
        // buttons.setBorder(BorderFactory.createEtchedBorder());

        Box alignV = Box.createVerticalBox();
        alignV.add(realTime);
        alignV.add(corrections);
        alignV.add(buttons);

        add(alignV);
    }

    public final void actionPerformed(final ActionEvent ae) {
        String command = ae.getActionCommand();

        if (command.equals("Done")) {
            master.switchScreen("Main");
            return;
        }

        if (master.switchScreen(command)) {
            JOptionPane.showMessageDialog(this,
                    "This function is not yet implemented", "Not Implemented",
                    JOptionPane.INFORMATION_MESSAGE);
        }

    }

    public final void update(final int[] realtime) {
        seconds.update(realtime[0], realtime[0]);
        map.update(realtime[4], realtime[4]);
        coolant.update(MegasquirtINC.THERMFACTOR[realtime[6]] - 40,
                255 - realtime[6]);
        baro.update(MegasquirtINC.BAROFACTOR[realtime[3]], realtime[3]);
        mat.update(MegasquirtINC.THERMFACTOR[realtime[5]] - 40, 255 - realtime[5]);
        tps.update(((double) realtime[7] / 255) * 100, realtime[7]);
        rpm.update(realtime[13] * 100, realtime[13]);

        pw.update((double) realtime[14] / 10, realtime[14] / 10);
        gamma.update(realtime[17]);
        batt.update((double) realtime[8] * 30 / 255, (realtime[8] * 30) / 255);
        ego.update(realtime[10]);
        barom.update(MegasquirtINC.BAROFACTOR[realtime[3]]);
        warm.update(realtime[12]);
        airDens.update(realtime[11]);
        ve.update(realtime[18]);
        acc.update(realtime[15]);
    }
}
